/*
 * interrupt_controller.c
 * OMAP L138
*/

#include "interrupt_controller.h"
#include "os_io.h"

/*
* GENERAL INFORMATION
*
* Entering an interrupt:
* > Change to appropriate mode
* > Save return address to r14_exc
* > Save CPSR in SPSR_exc
* > Disable IRQ (FIQ also disabled in case of an FIQ interrupt)
* > Force PC to vector address
*/

void _interrupt_vector_base(void);
void _exit_interrupt(void);

#if 0
void print_dummy(uint32_t *sp)
{
	#warning: Remove print_dummy
	printf("SP at: 0x%x\n", sp);

	uint8_t i = 0;
	printf("Trace\n");
	for (i = 0; i < 15; i++)
	{
		printf("0x%x\n", *(sp + i));
	}

	return;
}
#endif



void exception_handler(uint32_t code, uint32_t location)
{
	printf("Exception (code: 0x%x) from location 0x%x\n", code, location);
	while (1);
}




void initialize_interrupts()
{
	uint8_t i = 0;

	// Enable IRQ and FIQ in CPSR
	// This has already been done in the startup code

	ARM_INTC_GER = 0x00;	// Disable all interrupts

	// Disable and clear all system interrupts by default
	for (i = ARM_MAX_INTERRUPTS; i > 0; i--) {
		ARM_INTC_EICR = (i - 1);	// Disable interrupt
		ARM_INTC_SICR = (i - 1);	// Clear any pending status
	}

	// Enable Host interrupt lines
	ARM_INTC_HIER(0) = 0x03; // Enable FIQ/IRQ lines


	// Control interrupts mode
	ARM_INTC_CR = 0x00000008;	// Auto nesting

	ARM_INTC_VBR = (uint32_t)_interrupt_vector_base;
	ARM_INTC_VSR = 0x01;		// 8 byte spacing b/w vectors (branch instruction)
	ARM_INTC_VNR = (uint32_t)_exit_interrupt;

	// Enable Global interrupts
	ARM_INTC_GER = 0x01;
	
	return;
}

/*
* Install ISR for a particular interrupt, and enable interrupt
*/
void enable_interrupt(uint8_t interrupt_index)
{

	ARM_INTC_SICR = interrupt_index;	// clear any pending status
	ARM_INTC_EISR = interrupt_index;	// enable interrupt

	return;
}


